/**
 * Created on 2006-3-14
 *
 * Window - Preferences - Java - Code Style - Code Templates
 */
package com.luxx.util;

import org.dom4j.*;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;

import java.io.*;
import java.util.List;

/**
 *  XML文档组装和解析工具类
 *  @author lrq
 *
 *
 * Window - Preferences - Java - Code Style - Code Templates
 */
public class XMLUtils {
    /**
     * 缺省字符集
     * */
    public static final String DEFAULT_ENCODING = "UTF-8";
     
    /**
     * 私有构造函数，阻止非法调用构造函数
     * */
    private XMLUtils() {
    }
 
    /** 
     *  得到给定结点下的孩子节点
     *  @param element 节点
     *  @param name 子节点名称
     *  @return 子节点
     */
    public static Element child(Element element, String name) {
        return element.element(new QName(name, element.getNamespace()));
    }

    /**
     * 得到某个节点下的所有子节点
     * @param element 节点
     * @param name 属性名
     * @return 子节点List
     */
    public static List children(Element element, String name) {
        return element.elements(new QName(name, element.getNamespace()));
    }
     
     
    /**
     * 得到某个节点下的某个属性值
     * @param element 节点
     * @param name 属性名
     * @return 值(String类型)
     */
    public static String getAttribute(Element element, String name){
        Attribute attr = null;
        if(element!=null) {
            attr = element.attribute(name);
        }
        return attr.getValue();
    }
 
    /**
     * 得到节点属性值，并且作为日期型返回
     * @param element 节点
     * @param name 属性名
     * @return 值
     */
 
    public static java.util.Date getAttributeAsDate(Element element, String name){
        String value = getAttribute(element, name);
        return null;
    }
 
    /**
     * 得到某个节点下的属性信息，值以字符串的形式返回
     * @param element 节点
     * @param name 属性名
     * @return 值
     */
    public static String getAttributeAsString(Element element, String name){
        return getAttribute(element, name);
    }
 
    /**
     * 得到某个节点下的属性信息，值以整数的形式返回。
     * 如果没有值或是转化为整形，那么抛出异常。
     * @param element 节点
     * @param name 属性名
     * @return 值
     */
    public static int getAttributeAsInt(Element element, String name) {
        return Integer.parseInt(getAttribute(element, name));
    }
 
    /**
     * 得到某个节点下的属性信息，值以float的形式返回。
     * 如果没有值或是转化为float，那么抛出异常。
     * @param element 节点
     * @param name 属性名
     * @return 值
     */
    public static float getAttributeAsFloat(Element element, String name){
        return Float.parseFloat(getAttribute(element, name));
    }

    /**
     * 得到某个节点下的属性信息，值以长整数的形式返回。
     * 如果没有值或是转化为整形，那么抛出异常。
     * @param element 节点
     * @param name 属性名
     * @return 值
     */
    public static long getAttributeAsLong(Element element, String name){
        return Long.parseLong(getAttribute(element, name));
    }
 
    /**
     * 得到某个节点下的某名字的第一个孩子节点
     * @param element 节点
     * @param name 子节点名称
     * @return 值
     */
    public static Element getFirstChild(Element element, String name){
        List list = element.elements(new QName(name,element.getNamespace()));
        //如果数目大于0，那么直接取第一个就可以了
        if (list.size() > 0) {
            return (Element) list.get(0);
        }else {
           return null;
        }
    }
 
    /**
     * 得到同名兄弟节点,同名的第一个节点，可以是自己
     * @param element 节点
     * @return 节点
     */
    public static Element getFirstBrother(Element element){
        return getSibling(element, element.getName()).get(0);
    }
 
    /**
     * 按名称得到兄弟节点
     * @param element 节点
     * @param name 子节点名称
     * @return 节点
     */
    public static List<Element> getSibling(Element element, String name){
        List list = element.getParent().elements(name);
        return list;
    }
 
    /**
     * 得到给定节点的值,以字符串返回
     * @param element 节点
     * @return 值
     */
    public static String getContent(Element element){
        return element.getText();
    }







    /**************此处为分割线，以上是解析XML,以下是生成XML************************/








    /**
     * 给定父节点和子节点名称，得到子节点值
     * @param root 父节点
     * @param subTagName 子节点
     * @return 值
     */
    public static String getSubTagValue(Element root, String subTagName) {
        String returnString = root.elementText(subTagName);
        return returnString;
    }

    /**
     * 新Element节点，值为String类型
     * @param parent 父节点
     * @param name 新节点名称
     * @param value 新节点值
     * @return element
     */
    public static Element appendChild(Element parent,
                                      String name,
                                      String value) {
        Element element = parent.addElement(new QName(name, parent.getNamespace()));
        if (value != null) {
            element.addText(value);
        }
        return element;
    }
 
    /**
     * 增加新Element节点，无值
     * @param parent 父节点
     * @param name 新节点名称
     * @return Element 新建节点
     * @throws Exception
     */
    public static Element appendChild(Element parent, String name) {
        return parent.addElement(new QName(name, parent.getNamespace()));
    }

 
    /**
     * 检查文档dtd定义是否正确
     * @param document 文档节点
     * @param dtdPublicId dtd定义
     * @return boolean  相同返回true,否则false
     */
    public static boolean checkDocumentType(Document document,
                                            String dtdPublicId) {
        DocumentType documentType = document.getDocType();
        if (documentType != null) {
            String publicId = documentType.getPublicID();
            return publicId != null && publicId.equals(dtdPublicId);
        }
        return true;
    }
 
    /**
     * 新建文档
     * @return Document  文档节点
     */
    public static Document createDocument()
        throws Exception {
        DocumentFactory factory = new DocumentFactory();
        Document document = factory.createDocument();
        return document;
    }
    /**
     * 通过Reader读取Document文档
     * 如果encodingStr为null或是""，那么采用缺省编码GB2312
     * @param in Reader器
     * @param encoding 编码器
     * @return documment
     * @throws Exception
     */
    public static Document fromXML(Reader in, String encoding)
        throws Exception {
        try {
            if (encoding == null || encoding.equals("")) {
                encoding = DEFAULT_ENCODING;
            }
            SAXReader reader = new SAXReader();
            Document document = reader.read(in, encoding);
            return document;
        }
        catch (Exception ex) {
            throw new Exception(ex);
        }
    }
 
    /**
     * 给定输入流读取XML的Document。
     * 如果encodingStr为null或是""，那么采用缺省编码GB2312
     * @param inputSource 输入源
     * @param encoding 编码器
     * @return document
     * @throws Exception
     */
    public static Document fromXML(InputStream inputSource, String encoding)
        throws Exception {
        try {
            if (encoding == null || encoding.equals("")) {
                encoding = DEFAULT_ENCODING;
            }
            SAXReader reader = new SAXReader();
            Document document = reader.read(inputSource, encoding);
            return document;
        }
        catch (Exception ex) {
            throw new Exception(ex);
        }
    }

    /**
     * 直接从字符串得到XML的Document
     * @param file 把一个xml文件转化为XML的Document对象
     * @param encoding 编码器
     * @return <code>Document</code>
     * @throws Exception
     */
    public static Document fromXML(File file, String encoding)
            throws Exception {
        return fromXML(new FileInputStream(file), encoding);
    }

    /**
     * 直接从字符串得到XML的Document
     * @param xmlString 把一个字符串文本转化为XML的Document对象
     * @param encoding 编码器
     * @return <code>Document</code>
     * @throws Exception
     */
    public static Document fromXML(String xmlString, String encoding) throws Exception {
        return fromXML(new StringReader(xmlString), encoding);
    }

    /**
     * @param object    接受String,Reader,InputStream和File类型参数
     * @return  document
     * @throws Exception
     */
    public static Document fromXML(Object object)
            throws Exception {
        try {
            Document document;
            if(object instanceof Reader) {
                document = fromXML((Reader) object, DEFAULT_ENCODING);
            } else if (object instanceof InputStream) {
                document = fromXML((InputStream) object, DEFAULT_ENCODING);
            } else if (object instanceof String) {
                document = fromXML((String) object, DEFAULT_ENCODING);
            } else if (object instanceof File) {
                document = fromXML((File) object, DEFAULT_ENCODING);
            } else {
                document = null;
            }
            return document;
        }
        catch (Exception ex) {
            throw new Exception(ex);
        }
    }
    /**
     * 把XML的Document转化为java.io.Writer输出流
     * 不支持给定Schema文件的校验
     * @param document XML文档
     * @param outWriter 输出写入器
     * @param encoding 编码类型
     * @throws Exception 如果有任何异常转化为该异常输出
     */
    public static void toXML(Document document, Writer outWriter,
                             String encoding)
        throws Exception {
        //
        OutputFormat outformat = OutputFormat.createPrettyPrint();
        if (encoding == null || encoding.trim().equals("")) {
            encoding = DEFAULT_ENCODING;
        }
        //设置编码类型
        outformat.setEncoding(encoding);
        XMLWriter xmlWriter = null;
        try {
            xmlWriter = new XMLWriter(outWriter, outformat);
            xmlWriter.write(document);
            xmlWriter.flush();
        }
        catch (IOException ex) {
            throw new Exception(ex);
        }
        finally {
            if (xmlWriter != null) {
                try {
                    xmlWriter.close();
                }
                catch (IOException ex) {
                }
            }
        }
    }
 
    /**
     * 不支持给定Schema文件的校验
     * @param document XML文档
     * @param outStream 输出写入器
     * @param encoding 编码类型
     * @throws Exception 如果有任何异常转化为该异常输出
     */
    public static void toXML(Document document, OutputStream outStream,
                             String encoding)
        throws Exception {
        //
        OutputFormat outformat = OutputFormat.createPrettyPrint();
        if (encoding == null || encoding.trim().equals("")) {
            encoding = DEFAULT_ENCODING;
        }
        //设置编码类型
        outformat.setEncoding(encoding);
        XMLWriter xmlWriter = null;
        try {
            xmlWriter = new XMLWriter(outStream, outformat);
            xmlWriter.write(document);
            xmlWriter.flush();
        }
        catch (IOException ex) {
            throw new Exception(ex);
        }
        finally {
            if (xmlWriter != null) {
                try {
                    xmlWriter.close();
                }
                catch (IOException ex) {
                }
            }
        }
    }
 
    /**
     * 把XML文档转化为String返回
     * @param document 要转化的XML的Document
     * @param encoding 编码类型
     * @return <code>String</code>
     * @throws Exception 如果有任何异常转化为该异常输出
     */
    public static String toXML(Document document, String encoding)
        throws Exception {
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        toXML(document, stream, encoding);
        if (stream != null) {
            try {
                stream.close();
            }
            catch (IOException ex) {
            }
        }
        return stream.toString();
    }
    /**
     * 重载toXML，默认编码为 DEFAULT_ENCODING
     */
    public static String toXML(Document document) throws Exception {return toXML(document,DEFAULT_ENCODING);}

    /*public static void main(String[] args){
        Scanner in = new Scanner(System.in);
        String reg = "1[0-9]{10}";
        while(true) {
            String mobile = in.next().trim();
            StopWatch clock = new StopWatch();
            clock.start();
            if (StringUtils.isBlank(mobile) || !StringUtils.isNumeric(mobile) || !mobile.startsWith("1") || mobile.length() != 11) {
                System.out.println(false);
            }else
                System.out.println(true);
            clock.stop();
            System.out.println(clock.getTime());
            StopWatch clock2 = new StopWatch();
            clock2.start();
            System.out.println(mobile.matches(reg));
            clock2.stop();
            System.out.println(clock2.getTime());

        }
    }*/

}